// _Exercise2_Affine.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include "cv.h"
#include "highgui.h"
#include "math.h"
#include "stdio.h"

CvRect box;
IplImage *origin;
bool drawing_box=false;

void DrawBox(IplImage* img, CvRect rect)
{
	cvRectangle(img,cvPoint(box.x,box.y),cvPoint(box.x+box.width, box.y+box.height),cvScalar(0xff,0x00,0x00));	
}

void MyMouse_callback(int event, int x, int y, int flag, void* param)
{
	IplImage* image = (IplImage*)param;
	switch(event)
	{
	case CV_EVENT_LBUTTONDOWN:
		{
			//cvZero(image);
			cvCopyImage(origin,image);
			drawing_box = true;
			box = cvRect(x,y,0,0);
		}
		break;
	case CV_EVENT_MOUSEMOVE:
		{
			if(drawing_box)
			{
				box.width = x-box.x;
				box.height = y - box.y;
			}
		}
		break;
	case CV_EVENT_LBUTTONUP:
		{
			drawing_box = false;
			if(box.width < 0)
			{
				box.x += box.width;
				box.width = -box.width;
			}
			if(box.height < 0)
			{
				box.y += box.height;
				box.height = -box.height;
			}
			DrawBox(image,box);
		}
		break;
	}
}

bool RotationImage(IplImage* src,IplImage* dsc,float angle)
{
	int width = src->width;
	int height = src->height;
	int widthstep = src->widthStep;
	int depth = src->depth;
	int channel = src->nChannels;
	cvZero(dsc);

	uchar* origin = (uchar*)src->imageData;
	uchar* res = (uchar*)dsc->imageData;

	double cosX = cos(angle*CV_PI/180);
	double sinX = sin(angle*CV_PI/180);
	double tanX = tan(angle*CV_PI/180);

	int xA = cvRound(cosX*width);
	int yA = cvRound(sinX*width);


	int newHeight = cvRound(height*cosX + width*sinX);
	for(int i =0; i< newHeight; i++)
	{
		/*
		if(i>dsc->height)
		break;
		*/
		//		int newWidth = cvRound(tanX*i);
		for(int j = 0; j < dsc->width;j++)
		{
			// 			if(j >= i*1/tanX)
			// 				break;
			int X = cvRound(-cosX*j - i*sinX);
			int Y = cvRound(-sinX*j + cosX*i);

			if(X < 0)
				X = width + X;
			if(Y < 0)
				Y = height + Y;


			for(int k = 0; k < channel ; k++)
			{
				if(Y>=src->height || X >= src->width  /*|| X < 0 || Y < 0*/ )
				{
					break;
				}
				if((i - yA - (-1/tanX)*(j - xA))*(-yA - (-1/tanX)*(-xA)) < 0)
					break;

				res[i*dsc->widthStep+j*dsc->nChannels + k] = origin[(Y)*src->widthStep+(X)*src->nChannels+k];
				//printf("(%d, %d)\n",X,Y);
			}
		}

	}

	// X = -sinX.posX + posY.cosX
	// Y = cosX.posX + sinY.posY

	return true;

}

bool MyOtherRotate(IplImage* src, IplImage* dsc, double angle)
{
	CvMat* rot_mat = cvCreateMat(2,3,CV_32FC1);
	//	CvPoint2D32f center = cvPoint2D32f(src->width/2,src->height/2);

	CvPoint2D32f center = cvPoint2D32f(0,0);
	cv2DRotationMatrix(center,angle,1,rot_mat);
	cvWarpAffine(src,dsc,rot_mat);
	return true;
}



bool ScaleImage(IplImage* src, IplImage* dsc, float ratio)
{
	uchar* origin = (uchar*)src->imageData;
	uchar* res = (uchar*)dsc->imageData;
	if(ratio <= 0)
		ratio = -ratio;
	cvZero(dsc);
	int newWidth = cvRound(src->width*ratio);
	int newHeight = cvRound(src->height*ratio);
	for(int i =0; i < newHeight; i++)
	{
		int Y = cvRound(i/ratio);
		for(int j = 0; j < newWidth; j++)
		{
			int X = cvRound(j/ratio);

			for (int k = 0; k < dsc->nChannels; k++)
			{
				res[i*dsc->widthStep + j*dsc->nChannels + k] = origin[Y*src->widthStep + X * src->nChannels + k];
			}
		}

	}

	return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
	box = cvRect(-1,-1,0,0);
	cvNamedWindow("Main");
	cvNamedWindow("Result");
	IplImage* img = cvLoadImage("D:\\test.jpg");
	//	IplImage* temp  = cvCloneImage(img);
	double ratio = 2;
	IplImage* temp = cvCreateImage(cvSize(img->width*ratio,img->height*ratio),img->depth,img->nChannels);


	RotationImage(img,temp,15);
	//	ScaleImage(img,temp,ratio);
	MyOtherRotate(img,temp,10);

	cvShowImage("Main",img);
	cvShowImage("Result",temp);
	cvWaitKey(0);

	//	cvSetMouseCallback("Main",MyMouse_callback,img);
	/*

	while(1)
	{
	cvCopyImage(image,temp);
	if(drawing_box)
	{
	DrawBox(temp,box);
	}
	if(box.height > 0 && box.width > 0)
	{
	IplImage* sub_img = cvCreateImageHeader(cvSize(box.width,box.height),temp->depth,temp->nChannels);
	sub_img->origin = temp->origin;
	sub_img->widthStep = temp->widthStep;
	sub_img->imageData = temp->imageData + box.y*temp->widthStep + box.x*temp->nChannels;

	int command;

	printf("Plz input yr command: 1. Zoom 2. Rotate \n ");
	scanf("%d", &command);
	if(command==1)
	{
	int my_ratio;
	printf("Plz input yr command: 1. Zoom 2. Rotate \n ");
	scanf("%d", &my_ratio);

	}


	cvReleaseImageHeader(&sub_img);
	}


	if(cvWaitKey(15)==27)
	break;
	}
	*/


	cvReleaseImage(&img);
	cvReleaseImage(&temp);
	cvDestroyWindow("Main");

	return 1;

}


